﻿using KPIS.GERP.Models.SYS;
using System;
using KPIS.GERP.Models.SYS.ViewModel;
using System.Linq;
using KPIS.GERP.Models;
using System.Data.Entity;


namespace KPIS.GERP.WCF.SYS
{
    public partial class SysApprovalService
    {
        public CalAppPrcIdVm FindAppPrcId(CalAppPrcIdVm model)
        {
            // 1 ถ้าระบุ AppPrcId มาตรงๆ ก็ให้ใช้ตัวนั้น
            if (model.AppPrcId != 0)
            {
                model.Reasons = "มีการระบุ AppPrcId";
                return model;
            }
            // 2 ถ้าไม่ระบุและไม่มี Mapping ให้ไปหา DefaultProcess ของ Group นั้น ถ้ามี Mapping ให้หาเอาว่าจะใช้ AppPrcId อะไร
            ApproveProcessGroup appPrcGrp ;
            var db = new GERPContext(true);
            if ((appPrcGrp = db.ApproveProcessGroups.FirstOrDefault(o => o.AppPrcGrpId == model.AppPrcGrpId)) == null)
            {
                throw new Exception("กรุณาระบุระบบอนุมัติ ApproveProcessGroup");
            }

            // 3 กรณีระบุ group มา และระบุว่าใช้ Reference Entity ให้ไปโหลด Type ของ Entity นั้น
            if (appPrcGrp.UseReferenceEntity)
            {
                try
                {
                    /*select entity.AppPrcId from hrm_ps_absence item 
inner join hrm_ps_absence_types entity on item.absence_type_seq = entity.absence_type_seq
where item.absence_seq = 423*/

                    string query = string.Format(@"
update {2} set {0} = null where {0} not in (
select p.AppPrcId from SysApproveProcess p inner join SysApproveProcessGroup g on p.AppPrcGrpId = g.AppPrcGrpId
where p.RecordStatus != 'D' and g.RecordStatus != 'D'
);

select entity.{0} from {1} item 
inner join {2} entity on item.{3} = entity.{4}
where item.{5} = {6}", appPrcGrp.Entity_ColAppPrcIdName,
                                                 appPrcGrp.Item_TblName,
                                                 appPrcGrp.Entity_TblName,
                                                 appPrcGrp.Item_ColEntityRefId,
                                                 appPrcGrp.Entity_ColId,
                                                 appPrcGrp.Item_ColId,
                                                 model.RefId);
                    var appPrcGrpIds = db.Database.SqlQuery<int?>(query).ToArray();
                    var prcGrpIds = appPrcGrpIds as int?[] ?? appPrcGrpIds.ToArray();
                    if (appPrcGrpIds != null && prcGrpIds.FirstOrDefault() != null)
                    {
                        var firstOrDefault = prcGrpIds.FirstOrDefault();
                        if (firstOrDefault != null)
                        {
                            model.AppPrcId =  firstOrDefault.Value;
                            model.Reasons = "ค้นจากตัวเลือกของข้อมูลที่เกี่ยวข้องใน " 
                                + db.ApproveProcesses.Include(o=>o.ApproveProcessGroup).First(o=>o.AppPrcId == model.AppPrcId).ApproveProcessGroup.Name;
                            return model;
                        }
                    }
                }
                catch (Exception ex)
                {
                    throw new Exception("Approve Process Group Use Ref. Entity But Can't load data from config", ex);
                }
            }
            var mapping = db.ApproveProcessMappings.Where(o => o.AppPrcGrpId == model.AppPrcGrpId).ToList();

            // 4 พบ Mapping ให้หาที่ตรงเงื่อนไขก่อน แล้วค่อ่ยไหลไปใช้ Default Process
            decimal value = model.Amount;
            foreach (var map in mapping)
            {
                switch (map.TypeOfCompare)
                {
                    case TypeOfCompare.LessThan:
                        if (value < map.ValueToCompare)
                        {
                            model.AppPrcId = map.AppPrcId;
                            model.Reasons = "ค้นเจอจากในเงื่อนไขวงเงิน";
                            model.ApproveProcessMapping = map;
                            return model;
                        }
                        break;
                    case TypeOfCompare.MoreThan:
                        if (value > map.ValueToCompare) 
                        {
                            model.AppPrcId = map.AppPrcId;
                            model.Reasons = "ค้นเจอจากในเงื่อนไขวงเงิน";
                            model.ApproveProcessMapping = map;
                            return model;
                        }
                        break;
                    case TypeOfCompare.Equal:
                        if (value == map.ValueToCompare) 
                        {
                            model.AppPrcId = map.AppPrcId;
                            model.Reasons = "ค้นเจอจากในเงื่อนไขวงเงิน";
                            model.ApproveProcessMapping = map;
                            return model;
                        }
                        break;
                    case TypeOfCompare.LessThanOrEqual:
                        if (value <= map.ValueToCompare) 
                        {
                            model.AppPrcId = map.AppPrcId;
                            model.Reasons = "ค้นเจอจากในเงื่อนไขวงเงิน";
                            model.ApproveProcessMapping = map;
                            return model;
                        }
                        break;
                    case TypeOfCompare.MoreThanOrEqual:
                        if (value >= map.ValueToCompare) 
                        {
                            model.AppPrcId = map.AppPrcId;
                            model.Reasons = "ค้นเจอจากในเงื่อนไขวงเงิน";
                            model.ApproveProcessMapping = map;
                            return model;
                        }
                        break;
                    case TypeOfCompare.NotEqual:
                        if (value != map.ValueToCompare) 
                        {
                            model.AppPrcId = map.AppPrcId;
                            model.Reasons = "ค้นเจอจากในเงื่อนไขวงเงิน";
                            model.ApproveProcessMapping = map;
                            return model;
                        }
                        break;
                }
            }

            //หา Mapping ที่ตรงเงื่อนไขไม่เจอ ใช้ DefaultProcess
            var appPrc = db.ApproveProcesses.FirstOrDefault(o => o.AppPrcGrpId == model.AppPrcGrpId && o.IsDefaultProcess);
            if (appPrc != null)
            {
                model.AppPrcId = appPrc.AppPrcId;
                model.Reasons = "ค้นเจอจากค่าเริ่มต้นของระบบอนุมัติ"; 
                return model;
            }else if(// หา Mapping default process ไม่เจอ ใช้ appprocess ตัวแรก
                (appPrc = db.ApproveProcesses.FirstOrDefault(o => o.AppPrcGrpId == model.AppPrcGrpId)) != null)
            {
                model.AppPrcId = appPrc.AppPrcId;
                model.Reasons = "ใช้ค่าประเภทอนุมัติแรกที่พบในระบบอนุมัติ"; 
                return model;
            }
            else
            {
                throw new Exception("ไม่พบประเภทการอนุมติ ApproveProcess");
            }
        }

        public int? GetTaskIdOfRef(int appPrcId, int refId)
        {
            var task = new GERPContext().Tasks.Where(o => o.AppPrcId == appPrcId && o.RefId == refId && o.RecordStatus != RecordStatus.DeletedStatus).OrderByDescending(o => o.TaskId).FirstOrDefault();
            if(task != null)
            {
                return task.TaskId;
            }
            return null;
        }
        public int? GetTaskIdOfRefInGroup(int appPrcGrpId, int refId)
        {
            using (var db = new GERPContext())
            {
                var task = db.Tasks.Where(o => 
                    o.ApproveProcess.AppPrcGrpId == appPrcGrpId &&
                    o.RefId == refId && 
                    o.RecordStatus != RecordStatus.DeletedStatus).OrderByDescending(o => o.TaskId).FirstOrDefault();
                
                if (task != null)
                {
                    return task.TaskId;
                }
                return null;
            }
        }
    }
}